package com.empire.module.member.service.transportationrecord;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.alibaba.fastjson.JSONObject;
import com.empire.framework.common.exception.util.ServiceExceptionUtil;
import com.empire.module.member.dal.dataobject.presentation.PresentationDO;
import com.empire.module.member.dal.dataobject.user.MemberUserDO;
import com.empire.module.member.enums.ErrorCodeConstants;
import com.empire.module.member.service.datahub.vo.TransportationRecordDataHubVO;
import com.empire.module.member.service.presentation.PresentationService;
import com.empire.module.member.service.presentationpersonrelation.PresentationPersonRelationService;
import com.empire.module.member.service.user.MemberUserService;
import com.empire.module.member.service.warningindividual.WarningIndividualService;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import com.empire.module.member.controller.admin.transportationrecord.vo.*;
import com.empire.module.member.dal.dataobject.transportationrecord.TransportationRecordDO;
import com.empire.framework.common.pojo.PageResult;
import com.empire.framework.common.util.object.BeanUtils;

import com.empire.module.member.dal.mysql.transportationrecord.TransportationRecordMapper;

import javax.annotation.Resource;

import java.io.IOException;
import java.io.OutputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.empire.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.empire.module.member.enums.ErrorCodeConstants.*;

/**
 * 交通记录 Service 实现类
 *
 * @author 主席大人
 */
@Slf4j
@Service
@Validated
public class TransportationRecordServiceImpl implements TransportationRecordService {

    private static final String TRANSPORT_TOPIC = "datahub-transportation-record-topic";

    @Resource
    private TransportationRecordMapper transportationRecordMapper;
    @Resource
    private MemberUserService memberUserService;
    @Resource
    private WarningIndividualService warningIndividualService;
    @Resource
    private PresentationService presentationService;
    @Resource
    private PresentationPersonRelationService presentationPersonRelationService;

//    @KafkaListener(topics = TRANSPORT_TOPIC, groupId = "warning-gather-group")
    public void receiveDataHubMessage(String message) {
        try {
            // 解析DataHub消息（注意：此处ActiveGather需改为ActiveGather）
            TransportationRecordDataHubVO dataHubVO =
                    JSONObject.parseObject(message, TransportationRecordDataHubVO.class);
            log.info("接收到DataHub数据: idNumber={}, time={}",
                    dataHubVO.getIdNumber(), dataHubVO.getBusstarttime());
            MemberUserDO userDO = memberUserService.getByIdCard(dataHubVO.getIdNumber());
            if (userDO != null) {
                TransportationRecordDO transportationRecordDO = new TransportationRecordDO();
                BeanUtils.copyProperties(dataHubVO, transportationRecordDO);
                transportationRecordDO.setPersonId(userDO.getId());
                transportationRecordDO.setCreateTime(LocalDateTime.now());
                transportationRecordMapper.insert(transportationRecordDO);
                if (transportationRecordDO.getId() > 0L) {
                    warningIndividualService.createTrasportWarningIndividual(transportationRecordDO);
                }
            }

        } catch (Exception e) {
            log.error("处理DataHub消息异常", e);
        }
    }

    @Override
    public Long createTransportationRecord(TransportationRecordSaveReqVO createReqVO) {
        // 插入
        TransportationRecordDO transportationRecord = BeanUtils.toBean(createReqVO, TransportationRecordDO.class);
        transportationRecordMapper.insert(transportationRecord);
        // 返回
        return transportationRecord.getId();
    }

    @Override
    public void updateTransportationRecord(TransportationRecordSaveReqVO updateReqVO) {
        // 校验存在
        validateTransportationRecordExists(updateReqVO.getId());
        // 更新
        TransportationRecordDO updateObj = BeanUtils.toBean(updateReqVO, TransportationRecordDO.class);
        transportationRecordMapper.updateById(updateObj);
    }

    @Override
    public void deleteTransportationRecord(Long id) {
        // 校验存在
        validateTransportationRecordExists(id);
        // 删除
        transportationRecordMapper.deleteById(id);
    }

    private void validateTransportationRecordExists(Long id) {
        if (transportationRecordMapper.selectById(id) == null) {
            throw exception(TRANSPORTATION_RECORD_NOT_EXISTS);
        }
    }

    @Override
    public TransportationRecordDO getTransportationRecord(Long id) {
        return transportationRecordMapper.selectById(id);
    }

    @Override
    public PageResult<TransportationRecordDO> getTransportationRecordPage(TransportationRecordPageReqVO pageReqVO) {
        return transportationRecordMapper.selectPage(pageReqVO);
    }

    /**
     * 生成交通记录Word文档并下载
     */
    public void exportTransportationRecords(Long presentationId, String fileName, OutputStream outputStream) {
        XWPFDocument document = null;
        try {
            // 1. 获取基础数据
            PresentationDO presentationDO = presentationService.getById(presentationId);
            if (presentationDO == null) {
                throw ServiceExceptionUtil.exception(ErrorCodeConstants.PRESENTATION_NOT_EXISTS);
            }
            Date startTime = presentationDO.getStartTime();
            Date endTime = presentationDO.getEndTime();
            Set<Long> personIdSet = presentationPersonRelationService.getPresentationPersonIds(presentationId);

            // 2. 创建文档对象
            document = new XWPFDocument();

            // 3. 添加文档属性（解决app.xml相关错误）
            setDocumentProperties(document);

            // 4. 添加标题
            XWPFParagraph title = document.createParagraph();
            title.setAlignment(ParagraphAlignment.CENTER);
            XWPFRun titleRun = title.createRun();
            titleRun.setText(fileName.substring(0, fileName.lastIndexOf(".")));
            titleRun.setFontSize(16);
            titleRun.setBold(true);
            titleRun.addBreak();

            // 5. 获取人员信息映射
            Map<Long, MemberUserDO> userMap = new HashMap<>();
            if (!personIdSet.isEmpty()) {
                List<MemberUserDO> memberUserDOS = memberUserService.listByIds(personIdSet);
                userMap = memberUserDOS.stream()
                        .collect(Collectors.toMap(
                                MemberUserDO::getId,
                                Function.identity(),
                                (existing, replacement) -> existing
                        ));
            }

            // 6. 查询交通记录
            List<TransportationRecordDO> recordList = transportationRecordMapper.selectPresentationList(
                    personIdSet,
                    LocalDateTimeUtil.of(startTime),
                    LocalDateTimeUtil.of(endTime)
            );

            // 7. 格式化时间显示
            // 7. 格式化时间显示
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM月dd日HH时mm分");

// 新增：按personId分组，并按createTime升序排序
            Map<Long, List<TransportationRecordDO>> groupedRecords = recordList.stream()
                    .collect(Collectors.groupingBy(
                            TransportationRecordDO::getPersonId,
                            Collectors.collectingAndThen(
                                    Collectors.toList(),
                                    list -> {
                                        // 按创建时间升序排序
                                        list.sort(Comparator.comparing(TransportationRecordDO::getCreateTime));
                                        return list;
                                    }
                            )
                    ));

            // 8. 添加每条交通记录（按分组处理）
            if (recordList.isEmpty()) {
                // 添加空数据提示
                XWPFParagraph emptyPara = document.createParagraph();
                XWPFRun emptyRun = emptyPara.createRun();
                emptyRun.setText("暂无交通记录数据");
                emptyRun.setFontSize(12);
            } else {
                // 用于标记是否是第一个分组，避免在最前面添加分隔线
                boolean isFirstGroup = true;

                // 遍历每个分组
                for (Map.Entry<Long, List<TransportationRecordDO>> entry : groupedRecords.entrySet()) {
                    Long personId = entry.getKey();
                    List<TransportationRecordDO> personRecords = entry.getValue();

                    // 非第一个分组前添加虚线分隔
                    if (!isFirstGroup) {
                        XWPFParagraph separator = document.createParagraph();
                        XWPFRun separatorRun = separator.createRun();
                        separatorRun.setText("---------------------------------------------------");
                        separatorRun.setFontSize(10);
                        separator.setSpacingAfter(50);
                        separator.setSpacingBefore(50);
                    }
                    isFirstGroup = false;

                    // 先添加人员名称作为分组标题
                    MemberUserDO user = userMap.get(personId);
                    String userName = user != null ? user.getName() : "未知人员";

                    XWPFParagraph namePara = document.createParagraph();
                    XWPFRun nameRun = namePara.createRun();
                    nameRun.setText(userName + "的交通记录：");
                    nameRun.setFontSize(14);
                    nameRun.setBold(true);
                    namePara.setSpacingAfter(50);

                    // 写入该人员的所有交通记录
                    for (TransportationRecordDO record : personRecords) {
                        XWPFParagraph paragraph = document.createParagraph();
                        XWPFRun run = paragraph.createRun();

                        String timeStr = record.getStartTime() != null
                                ? record.getStartTime().format(formatter)
                                : "未知时间";
                        String transportType = getTransportTypeName(record.getType());
                        String tripInfo = buildTripInfo(record, transportType);

                        String content = String.format("%s许乘坐%s%s。",
                                timeStr, record.getTransportationNumber(), tripInfo);

                        run.setText(content);
                        run.setFontSize(12);
                        paragraph.setSpacingAfter(100);
                    }
                }
            }

            // 9. 写入输出流
            document.write(outputStream);
            outputStream.flush();

        } catch (Exception e) {
            log.error("生成交通记录Word失败", e);
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.PRESENTATION_FILE_DOWNLOAD_FAIL, e.getMessage());
        } finally {
            // 10. 确保资源关闭
            if (document != null) {
                try {
                    document.close();
                } catch (IOException e) {
                    log.error("关闭文档失败", e);
                }
            }
            try {
                outputStream.close();
            } catch (IOException e) {
                log.error("关闭输出流失败", e);
            }
        }
    }

    /**
     * 设置文档属性，解决app.xml相关错误
     */
    private void setDocumentProperties(XWPFDocument document) {
        XWPFDocument doc = document;
        // 设置基本文档属性
        doc.getProperties().getCoreProperties().setTitle("交通记录报告");
        doc.getProperties().getCoreProperties().setCreator("系统");
        doc.getProperties().getCoreProperties().setCreated(Optional.of(new Date()));

        // 解决app.xml错误的关键：初始化应用属性
        doc.getProperties().getExtendedProperties().getUnderlyingProperties().setApplication("Apache POI");
        doc.getProperties().getExtendedProperties().getUnderlyingProperties().setCompany("empire");
    }

    /**
     * 转换交通类型为文字描述
     */
    private String getTransportTypeName(Integer type) {
        if (type == null) {
            return "交通工具";
        }
        return switch (type) {
            case 0 -> "航班";
            case 1 -> "高铁";
            case 2 -> "汽车";
            default -> "交通工具";
        };
    }

    /**
     * 构建行程信息
     */
    private String buildTripInfo(TransportationRecordDO record, String transportType) {
        String start = record.getStartLocation() != null ? record.getStartLocation() : "未知地点";
        String end = record.getEndLocation() != null ? record.getEndLocation() : "未知地点";

        // 判断是出发还是到达
        if ("杭州".equals(end) && !"杭州".equals(start)) {
            return String.format("次%s返回%s", transportType, end);
        } else if ("杭州".equals(start) && !"杭州".equals(end)) {
            return String.format("次%s离开%s前往%s", transportType, start, end);
        } else {
            return String.format("次%s从%s前往%s", transportType, start, end);
        }
    }

}